/**
 * 连接类, 依赖boost::asio库, 由stream_server接收过来而创建的流套接字
 * 保证收到客户端发来的第一个报文后, 构造处理类交之处理.
 * 
 * protocol: 协议, 支持local流和tcp流
 * handle: 与流协议无关的处理类, 会构造一个此类并调用其operator(), 该类必须:
 *	1. 支持boost_tcp_socket类引用作为参数的构造函数
 *	2. 重载operator()操作符(两个参数, 参数1为char*数据接收缓冲区, 参数2为缓冲区大小, 参数3为首次接收到的字节数)
 *	    其中char*缓冲区, 处理类可以一直使用, 无需释放, 大小固定
 *   handle使用构造传入的socket自行处理回复内容
 *   handle类如果需要异步处理, 应继承自boost::enable_shared_from_this, 否则operator()返回后即析构
 * 
 * 开发者   : Marco
 * 创建时间 : 2016年7月29日, 下午2:09
 */

#ifndef __MARCO_BST_CONNECTION_HPP__
#define __MARCO_BST_CONNECTION_HPP__

#ifdef __cplusplus

#include <boost/bind.hpp>
#include <boost/asio/read.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <marco/marco.h>

#include "stream_basic.h"

namespace marco {
namespace bst {

/**
 * 流连接类
 * @param protocol 协议类型， marco::bstio::tcp或marco::bstio::ls
 * @param handle 处理类，与协议无关性，固定传入marco::bstio::tcp过去
 */
template <typename protocol, typename handle>
class connection : public boost::enable_shared_from_this<connection<protocol, handle> > {
public:
    connection(boost::asio::io_service& io_service) : socket_(io_service) { }
//    ~connection(void) { }
    
    /**
     * 获取socket, server类每次接收连接时需要传入tcp::socket对象, 对新连接的信息存储.
     * @return
     */
    boost::asio::basic_stream_socket<protocol>& socket() {
	return socket_;
    }

    /**
     * 开始处理入口, 新连接建立后, server类调用此函数, 必须收到一定数据, 构造处理类并调用其入口函数.
     */
    void operator()(void) {
//	out_log(log_lv_2, "Library new connection, fd: %d.\n", socket_.native_handle());
	socket_.async_read_some(boost::asio::buffer(buf, sizeof(buf)-1), 
		boost::bind(&connection<protocol, handle>::read_complete, this, 
		connection<protocol, handle>::shared_from_this(), boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
	// FIXME, 定时器,N秒没有回到则主动关闭,析构
    }
    
    /**
     * 智能指针指定的删除器, 当引用计数为0时调用, 调用, 此处删除原始指针
     * @param handle_ptr handle处理类指针, 由于没有使用shared_ptr默认删除器, 必须手动在此delete此原始指针
     * @param sptr 本类智能指针, 不传入的话会导致本类提前于handle类析构(handle有异步, 本类parse_over返回后计数就为0了)
     */
    void deleter(handle* handle_ptr, boost::shared_ptr<connection<protocol, handle> > sptr) {
	delete handle_ptr;	// 删除handle处理类
    }

private:
    /**
     * 首报文读取完成, 交由handle类处理
     * @param sptr 本类智能指针, 防止opertor()返回后析构
     * @param buf 接收数据的缓冲区
     * @param 
     */
    void read_complete(boost::shared_ptr<connection<protocol, handle> > sptr, boost::system::error_code err, 
	    int bytes_transferred) {
	if (err) { // 错误
//	    out_log(log_lv_2, "Library receive failed: %s\n", err.message().c_str());
	    return;
	}
	
	handle* h = new handle((tcpsock&)connection<protocol, handle>::socket_);

	// 指定删除器, 并将自身shared_ptr传入, 否则本类会被提前析构, 要等handle类计数为0后, 调用了deleter删除器, 才能析构本类
	boost::shared_ptr<handle> ptr(h, boost::bind(&connection<protocol, handle>::deleter,
		this, h, connection<protocol, handle>::shared_from_this()));
	(*ptr)(buf, sizeof(buf), bytes_transferred);
    }
    
    boost::asio::basic_stream_socket<protocol> socket_;
    char buf[4096];
    
    connection(const connection& orig); // 禁用拷贝构造
    connection& operator=(const connection& orig); // 禁用赋值

#if (__cplusplus >= 201103L)
    connection(connection&& orig) = delete; // 移动构造禁用
    connection& operator=(connection&& orig) = delete; // 移动赋值运算符重载禁用
#endif
};

} // namespace boost
} // namespace marco
#endif // __cplusplus
#endif /* __MARCO_BST_CONNECTION_HPP__ */